package org.su.webadapter.template;

import org.su.generalmvc.core.IXsshApplicationContext;
import org.su.generalmvc.core.InitialContext;
import org.su.webadapter.IUserSession;
import org.su.webadapter.velocity.HtmlGenerateException;
import org.su.webadapter.velocity.VelocityUtils;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.context.Context;
import org.apache.velocity.io.VelocityWriter;
import org.apache.velocity.util.SimplePool;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.HashMap;
import java.util.Map;

public class VelocityTemplate implements ITemplateEngine {

	private IXsshApplicationContext applicationContext = InitialContext
			.getInstance().getContext();
	private VelocityEngine ve = null;

	public void setEngine(Object engine) {
		this.ve = (VelocityEngine) engine;
	}
	
	public VelocityEngine getEngine() {
		return ve;
	}


	@Override
	public String generateHtml(Map<String, ?> data, String path) {
		Template t;
		StringWriter writer = null;
		try {
			t = ve.getTemplate(path);
			VelocityContext context = new VelocityContext(data);
			context.put("VH", VelocityUtils.getInstance());
			writer = new StringWriter();
			t.merge(context, writer);
			return writer.toString();
		} catch (Exception e) {
			throw new HtmlGenerateException(e);
		}
	}

	/**
	 * 
	 */
	public void generateHtml(Map<String, ?> data, String path,
			HttpServletRequest request, HttpServletResponse response) {
		Template t;
		try {
			t = ve.getTemplate(path);
			generateHtml(data, t, request, response);
		} catch (Exception e) {
			throw new HtmlGenerateException(e);
		}
	}

	@Override
	public void generateHtml(Map<String, ?> data, Template t,
			HttpServletRequest request, HttpServletResponse response) {

		VelocityContext context = new VelocityContext(data);
		initContext(context, request);

		// context.put("sysBasePath", getBasePath(request));
		context.put("applicationContext", applicationContext);
		mergeTemplate(t, context, response);
	}
//----------------------------------------------------------------------------------
	@Override
	public String generateHtml(Object data, String path) {
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("sshObject", data);
		return generateHtml(map, path);
	}

	@Override
	public void generateHtml(Object data, String path,
			HttpServletRequest request, HttpServletResponse response) {
		Template t;
		try {
			t = ve.getTemplate(path);
			generateHtml(data, t, request, response);
		} catch (Exception e) {
			throw new HtmlGenerateException(e);
		}
		
	}

	@Override
	public void generateHtml(Object data, Template t,
			HttpServletRequest request, HttpServletResponse response) {
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("sshObject", data);
		generateHtml(map,t,request,response);
	}
//------------------------------------------------------------------------
	private void initContext(VelocityContext context, HttpServletRequest request) {
		context.put("sshUtil", VelocityUtils.getInstance());
		context.put("VH", VelocityUtils.getInstance());
		context.put("request", request);
		context.put("s_user", request.getSession().getAttribute(IUserSession.USER_SESSION));
	}

	@Override
	public void generateFile(Map<String, ?> data, String srcPath, String decPath) {
		generateFile(data, srcPath, decPath,null);
	}

	@Override
	public void generateFile(Map<String, ?> data, String srcPath, String decPath, HttpServletRequest request) {
		try {
			File file = new File(decPath);
			File parent = file.getParentFile();
			if (!parent.exists()) {
				if (!parent.mkdirs()) {
					throw new FileNotFoundException(file.getAbsolutePath());
				}
			}

			Template t = ve.getTemplate(srcPath);
			VelocityContext context = new VelocityContext(data);
			if (request != null) {
				initContext(context, request);
			}

			BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(
					new FileOutputStream(file), applicationContext.getConfig()
							.getEncoding()));
			try {
				t.merge(context, writer);
			} finally {
				writer.close();
			}
		} catch (Exception e) {
			throw new HtmlGenerateException(e);
		}
	}

	@Override
	public void writeHtml( Map<String, ?> data, File file, String templateStr) {

		String encode = applicationContext.getConfig().getEncoding();
		String log = file.getName();
		OutputStreamWriter output = null;
		try {
			output = new OutputStreamWriter(new FileOutputStream(file), encode);
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
		writeHtml(data, templateStr, log, output);

	}

	private static SimplePool writerPool = new SimplePool(40);

	/**
	 * 
	 */
	@Override
	public String writeHtml(Map<String, ?> data, String templateStr,
			String vmlog) {
		StringWriter sw = new StringWriter();
		// String encode = applicationContext.getConfig().getEncoding();
		writeHtml(data, templateStr, vmlog, sw);
		return sw.toString();
	}

	private void writeHtml(Map<String, ?> data, String templateStr,
			String vmlog, final Writer sw) {
		if (data == null) {
			data = new HashMap<String, Object>();
		}
		VelocityContext context = new VelocityContext(data);
		context.put("VH", VelocityUtils.getInstance());
		VelocityWriter vw = (VelocityWriter) writerPool.get();
		if (vw == null) {
			vw = new VelocityWriter(sw, 4 * 1024, true);
		} else {
			vw.recycle(sw);
		}
		try {
			ve.evaluate(context, vw, vmlog, templateStr);
			if (vw != null) {
				vw.flush();
				vw.recycle(null);
				writerPool.put(vw);
			}
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}

	
	@Override
	public void mergeTemplate(Template template, Context context,
			HttpServletResponse response) {
		Writer vm;
		try {
			vm = response.getWriter();
			try {
				template.merge(context, vm);
			} finally {
				vm.close();
			}
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}

}
